﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Xml;

namespace UMLDraw
{
    //объявление класса элемент Переход
    public class Transfer
    {
        public string Name;
        public string Text;
        public string FromName;
        public string ToName;
        public int XCoor;
        public int YCoor;
        public TreeNode Node;
        public Microsoft.VisualBasic.PowerPacks.LineShape Line = new Microsoft.VisualBasic.PowerPacks.LineShape();
        public Microsoft.VisualBasic.PowerPacks.LineShape specLine = new Microsoft.VisualBasic.PowerPacks.LineShape();
        public ToolTip Hint = new ToolTip();
        public TextBox Names = new TextBox();
        public Label LNames = new Label();

        public Point Zero = Point.Empty;
        public Point Drag = Point.Empty;
        public Point Drop = Point.Empty;

        public Transfer()
        {
            Name = "Transfer";
            Text = "Событие";
            FromName = "Unknown";
            ToName = "Unknown";
            Node = new TreeNode("Transfer");
            Node.Name = "Transfer";
            Node.Text = "Событие";
        }

        public void Initialize(string name, string text, string from, string to, Panel panel, Microsoft.VisualBasic.PowerPacks.ShapeContainer container)
        {
            Name = name;
            Text = text;
            Node.Name = name;
            Node.Text = text;
            FromName = from;
            ToName = to;

            Names.Name = name;
            Names.Text = text;
            Names.TextAlign = HorizontalAlignment.Center;
            Names.Size = new System.Drawing.Size(70, 20);
            Names.Location = new System.Drawing.Point((Line.StartPoint.X + Line.EndPoint.X) / 2 - Names.Width / 2, (Line.StartPoint.Y + Line.EndPoint.Y) / 2 - 25);
            Names.BorderStyle = BorderStyle.None;
            Names.TabIndex = 6 + Convert.ToInt16(name.Replace("Transfer", ""))*100;
            Names.BringToFront();
            Names.Hide();
            this.Names.MouseLeave += new System.EventHandler(this.LNames_MouseLeave);
            this.Names.Leave += new System.EventHandler(this.Name_Changed);
            panel.Controls.Add(Names);

            LNames.Name = name;
            LNames.Text = text;
            LNames.AutoSize = true;
            LNames.Location = new System.Drawing.Point((Line.StartPoint.X + Line.EndPoint.X) / 2 - LNames.Width / 2, (Line.StartPoint.Y + Line.EndPoint.Y) / 2 - 25);
            LNames.Cursor = System.Windows.Forms.Cursors.Hand;
            LNames.BorderStyle = BorderStyle.None;
            LNames.BackColor = Color.White;
            LNames.BringToFront();
            LNames.Hide();
            this.LNames.MouseClick += new System.Windows.Forms.MouseEventHandler(this.LNames_MouseClick);
            this.LNames.MouseMove += new System.Windows.Forms.MouseEventHandler(this.LNames_MouseMove);
            this.LNames.MouseDown += new System.Windows.Forms.MouseEventHandler(this.LNames_MouseDown);
            this.LNames.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.Tr_PreviewKeyDown);
            this.LNames.MouseUp += new System.Windows.Forms.MouseEventHandler(this.LNames_MouseUp);
            panel.Controls.Add(LNames);

            Line.Name = name;
            Line.BorderWidth = 2;
            Line.Cursor = System.Windows.Forms.Cursors.Hand;
            Line.Hide();
            Line.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.Tr_PreviewKeyDown);
            container.Shapes.AddRange(new Microsoft.VisualBasic.PowerPacks.Shape[] {
                Line});
            Line.EndPointChanged += new System.EventHandler(this.ChangeEnd);
            Line.StartPointChanged += new System.EventHandler(this.ChangeStart);

            specLine.Name = name;
            specLine.BorderWidth = 1;
            specLine.Cursor = System.Windows.Forms.Cursors.Hand;
            specLine.BorderStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            specLine.Hide();
            specLine.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.Tr_PreviewKeyDown);
            container.Shapes.AddRange(new Microsoft.VisualBasic.PowerPacks.Shape[] {
                specLine});  
        }

        private void Name_Changed(object sender, EventArgs e)
        {
            Control c = sender as Control;
            if (Text != c.Text)
            {
                Text = c.Text;
                LNames.Text = c.Text;
                Names.Select(0, 0);
                UMLDraw.MainForm.WPlace.tree.Nodes[c.Name].Text = c.Text;
                Hint.SetToolTip(Names, Names.Text);
                MainForm link = new MainForm();
                link.NewHistoryRec();
            }
        }
        private void Tr_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            Microsoft.VisualBasic.PowerPacks.LineShape c = sender as Microsoft.VisualBasic.PowerPacks.LineShape;
            if (e.KeyValue == 46)
            {
                Line.Dispose();
                Names.Dispose();
                LNames.Dispose();
                specLine.Dispose();
                UMLDraw.MainForm.WPlace.tree.Nodes[c.Name].Remove();
            }
        }

        private void LNames_MouseLeave(object sender, EventArgs e)
        {
            LNames.Show();
            Names.Hide();
        }

        private void LNames_MouseClick(object sender, MouseEventArgs e)
        {
            LNames.Hide();
            Names.Show();
            Names.BringToFront();
            Names.Select(0, 0);
        }


        private void LNames_MouseDown(object sender, MouseEventArgs e)
        {
            Control c = sender as Control;
            Zero = c.Location;

            Drag.X = Cursor.Position.X;
            Drag.Y = Cursor.Position.Y;
            c.Focus();
        }
        private void LNames_MouseMove(object sender, MouseEventArgs e)
        {
            Control c = sender as Control;
            if (e.Button == MouseButtons.Left)
            {
                Drop.X = Zero.X + Cursor.Position.X - Drag.X;
                Drop.Y = Zero.Y + Cursor.Position.Y - Drag.Y;
                c.Location = Drop;
                Names.Location = new System.Drawing.Point(Drop.X,Drop.Y);
                LNames.Location = new System.Drawing.Point(Drop.X, Drop.Y);
                double x1 = (Line.StartPoint.X + Line.EndPoint.X) / 2 ;
                double y1 = (Line.StartPoint.Y + Line.EndPoint.Y) / 2;
                double x2 = Drop.X + LNames.Width / 2;
                double y2 = Drop.Y + LNames.Height / 2;
                if (Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2)) > 60)
                {
                    specLine.X1 = (int)x1;
                    specLine.X2 = (int)x2;
                    specLine.Y1 = (int)y1;
                    specLine.Y2 = (int)y2;
                    specLine.Show();
                    Names.BringToFront();
                    Names.Refresh();
                    LNames.BringToFront();
                    LNames.Refresh();
                }
                else
                {
                    specLine.Hide();
                }
            }
        }

        private void LNames_MouseUp(object sender, MouseEventArgs e)
        {
            Control c = sender as Control;
         
            if (UMLDraw.MainForm.WPlace.CurrentAction == "SelectItem")       //если перемещается существующий элемент
            {
                if (XCoor != LNames.Location.X || YCoor != LNames.Location.Y)
                {
                    XCoor = LNames.Location.X;
                    YCoor = LNames.Location.Y;
                    UMLDraw.MainForm.WPlace.refreshAll();
                    MainForm link = new MainForm();
                    link.NewHistoryRec();
                }
            }
        }

        private void ChangeEnd(object sender, EventArgs e)
        {
            int X = this.Line.X2;
            int Y = this.Line.Y2;
            if (X != 0 && Y != 0)
            {
                if (this.FromName.Contains("State"))
                {
                    State From = UMLDraw.MainForm.STate[Convert.ToInt16(this.FromName.Replace("State", ""))];
                    double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[0].Y), 2));
                    int minIndex = 0;
                    for (int j = 1; j < 4; j++)
                    {
                        double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[j].Y), 2));
                        if (range < min)
                        {
                            min = range;
                            minIndex = j;
                        }
                    }

                    this.Line.X1 = From.PerimeterPoint[minIndex].X;
                    this.Line.Y1 = From.PerimeterPoint[minIndex].Y;
                    this.Line.Show();
                    RewriteEvent();
                }
                else
                    if (this.FromName.Contains("Comment"))
                    {
                        Comment From = UMLDraw.MainForm.CMent[Convert.ToInt16(this.FromName.Replace("Comment", ""))];
                        double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[0].Y), 2));
                        int minIndex = 0;
                        for (int j = 1; j < 4; j++)
                        {
                            double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[j].Y), 2));
                            if (range < min)
                            {
                                min = range;
                                minIndex = j;
                            }
                        }

                        this.Line.X1 = From.PerimeterPoint[minIndex].X;
                        this.Line.Y1 = From.PerimeterPoint[minIndex].Y;
                        this.Line.Show();
                    }
                    else
                        if (this.FromName.Contains("Output"))
                        {
                            Output From = UMLDraw.MainForm.OPut;
                            double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[0].Y), 2));
                            int minIndex = 0;
                            for (int j = 1; j < 4; j++)
                            {
                                double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[j].Y), 2));
                                if (range < min)
                                {
                                    min = range;
                                    minIndex = j;
                                }
                            }

                            this.Line.X1 = From.PerimeterPoint[minIndex].X;
                            this.Line.Y1 = From.PerimeterPoint[minIndex].Y;
                            this.Line.Show();
                            RewriteEvent();
                        }
                        else
                            if (this.FromName.Contains("Input"))
                            {
                                Input From = UMLDraw.MainForm.IPut;
                                double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[0].Y), 2));
                                int minIndex = 0;
                                for (int j = 1; j < 4; j++)
                                {
                                    double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - From.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - From.PerimeterPoint[j].Y), 2));
                                    if (range < min)
                                    {
                                        min = range;
                                        minIndex = j;
                                    }
                                }

                                this.Line.X1 = From.PerimeterPoint[minIndex].X;
                                this.Line.Y1 = From.PerimeterPoint[minIndex].Y;
                                this.Line.Show();
                                RewriteEvent();
                            }
            }
            specLine.Hide();
        }

        private void ChangeStart(object sender, EventArgs e)
        {
            int X = this.Line.X1;
            int Y = this.Line.Y1;

            if (X != 0 && Y != 0 && this.ToName != "Unknown")
            {
                if (this.ToName.Contains("State"))
                {
                    State To = UMLDraw.MainForm.STate[Convert.ToInt16(this.ToName.Replace("State", ""))];
                    double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[0].Y), 2));
                    int minIndex = 0;
                    for (int j = 1; j < 4; j++)
                    {
                        double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[j].Y), 2));
                        if (range < min)
                        {
                            min = range;
                            minIndex = j;
                        }
                    }

                    this.Line.X2 = To.PerimeterPoint[minIndex].X;
                    this.Line.Y2 = To.PerimeterPoint[minIndex].Y;
                    this.Line.Show();
                    RewriteEvent();
                }
                else
                    if (this.ToName.Contains("Comment"))
                    {
                        Comment To = UMLDraw.MainForm.CMent[Convert.ToInt16(this.ToName.Replace("Comment", ""))];
                        double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[0].Y), 2));
                        int minIndex = 0;
                        for (int j = 1; j < 4; j++)
                        {
                            double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[j].Y), 2));
                            if (range < min)
                            {
                                min = range;
                                minIndex = j;
                            }
                        }

                        this.Line.X2 = To.PerimeterPoint[minIndex].X;
                        this.Line.Y2 = To.PerimeterPoint[minIndex].Y;
                        this.Line.Show();
                    }
                    else
                        if (this.ToName.Contains("Output"))
                        {
                            Output To = UMLDraw.MainForm.OPut;
                            double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[0].Y), 2));
                            int minIndex = 0;
                            for (int j = 1; j < 4; j++)
                            {
                                double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[j].Y), 2));
                                if (range < min)
                                {
                                    min = range;
                                    minIndex = j;
                                }
                            }

                            this.Line.X2 = To.PerimeterPoint[minIndex].X;
                            this.Line.Y2 = To.PerimeterPoint[minIndex].Y;
                            this.Line.Show();
                            RewriteEvent();
                        }
                        else
                            if (this.ToName.Contains("Input"))
                            {
                                Input To = UMLDraw.MainForm.IPut;
                                double min = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[0].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[0].Y), 2));
                                int minIndex = 0;
                                for (int j = 1; j < 4; j++)
                                {
                                    double range = System.Math.Sqrt(System.Math.Pow(System.Math.Abs(X - To.PerimeterPoint[j].X), 2) + System.Math.Pow(System.Math.Abs(Y - To.PerimeterPoint[j].Y), 2));
                                    if (range < min)
                                    {
                                        min = range;
                                        minIndex = j;
                                    }
                                }

                                this.Line.X2 = To.PerimeterPoint[minIndex].X;
                                this.Line.Y2 = To.PerimeterPoint[minIndex].Y;
                                this.Line.Show();
                                RewriteEvent();
                            }
            }
            this.Line.SendToBack();
            specLine.Hide();
        }

        private void RewriteEvent()
        {
            Names.Location = new System.Drawing.Point((Line.StartPoint.X + Line.EndPoint.X) / 2 - Names.Width / 2, (Line.StartPoint.Y + Line.EndPoint.Y) / 2 - 25);
            LNames.Location = new System.Drawing.Point((Line.StartPoint.X + Line.EndPoint.X) / 2 - LNames.Width / 2, (Line.StartPoint.Y + Line.EndPoint.Y) / 2 - 25);
            LNames.BringToFront();

            if (!this.ToName.Contains("Comment") && !this.FromName.Contains("Comment"))
                LNames.Show();
            else
                this.Node.Text = "Связь с комментарием";
        }
    }
     
}
